package com.yunhe.authority.controller.authority;

import com.yunhe.authority.domain.authority.*;
import com.yunhe.authority.option.UserProperties;
import com.yunhe.authority.service.authority.StationService;
import com.yunhe.authority.service.authority.TokenService;
import com.yunhe.authority.service.authority.UserService;
import com.yunhe.common.annotation.OperationRecord;
import com.yunhe.common.constant.SystemConsts;
import com.yunhe.common.exception.ArgumentErrorException;
import com.yunhe.common.exception.ObjectNotFoundException;
import com.yunhe.common.exception.UsernamePasswordException;
import com.yunhe.common.model.ResultObject;
import com.yunhe.common.util.CollectionUtil;
import com.yunhe.common.util.DateTimeUtils;
import com.yunhe.common.util.MD5Util;
import com.yunhe.common.util.StringUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * 登陆Controller
 * @author liuronglei
 */
@Api(value = "login",description = "登录", tags = {"Authority_Login"})
@RestController
@RequestMapping("/login")
public class LoginController {

    /*
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String login(
            @RequestParam(value = "username", required = true) String userName,
            @RequestParam(value = "password", required = true) String password,
            @RequestParam(value = "rememberMe", required = true, defaultValue = "false") boolean rememberMe
    ) {
        logger.info("==========" + userName + password + rememberMe);
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(userName, password);
        token.setRememberMe(rememberMe);

        try {
            subject.login(token);
        } catch (AuthenticationException e) {
            e.printStackTrace();
//            rediect.addFlashAttribute("errorText", "您的账号或密码输入错误!");
            return "{\"Msg\":\"您的账号或密码输入错误\",\"state\":\"failed\"}";
        }
        return "{\"Msg\":\"登陆成功\",\"state\":\"success\"}";
    }

    @RequestMapping("/")
    @ResponseBody
    public String index() {
        return "no permission";
    }
    */

    @Autowired
    private UserService userService;
    @Autowired
    private TokenService tokenService;
    @Autowired
    private StationService stationService;

    @Autowired
    private UserProperties userProperties;

    private static final String SALT_V = "@yqlh";

    /**
     * 根据用户名和密码获得用户（执行登录）
     * @param name 键
     * @param password 值
     */
//    @ApiOperation("根据用户名和密码获得用户（执行登录）")
//    @ApiImplicitParams({
//            @ApiImplicitParam(name = "name", value = "用户名", dataType = "string", paramType = "query"),
//            @ApiImplicitParam(name = "password", value = "密码", dataType = "string", paramType = "query")
//    })
//    @RequestMapping(method = RequestMethod.POST)
//    public ResponseEntity<ResultObject> login(@RequestParam("name") Optional<String> name,
//                                              @RequestParam("password") Optional<String> password)
//            throws ArgumentErrorException, UsernamePasswordException {
//        if (!name.isPresent()) {
//            throw new UsernamePasswordException("用户名不能为空");
//        } else if (!password.isPresent()) {
//            throw new UsernamePasswordException("密码不能为空");
//        }
//        User user = userService.findByNameAndPassword(name.get(), password.get());
//        if (user == null) {
//            throw new UsernamePasswordException("用户名或密码错误");
//        } else if (user.getActivity().equals(false)) {
//            throw new UsernamePasswordException("该用户已过期，无法登录");
//        } else if (!CollectionUtil.isEmpty(user.getRole())  && user.getRole().getActivity().equals(false)) {
//            throw new UsernamePasswordException("该用户已过期，无法登录");
//        } else if (user.getRole() == null) {
//            throw new UsernamePasswordException("该用户已过期，无法登录");
//        } else {
//            if (user.getRole() != null && user.getRole().getId() != null) {
//                List<Station> list = (List<Station>)stationService.findByRoleId(user.getRole().getId());
//                if (list == null || list.size() == 0) {
//                    throw new UsernamePasswordException("当前用户没有数据权限，请联系管理员");
//                }
//            }
//        }
//        String token = tokenService.getToken(user);
//        Map<String, Object> result = new HashMap<>();
//        result.put("token", token);
//        result.put("user", user);
//        return new ResponseEntity<>(new ResultObject<>(result), HttpStatus.OK);
//    }

    /**
     * 添加token值
     * @param key 键
     * @param value 值
     * @param liveTime 过期时间（秒）
     */
//    @ApiOperation("添加token值")
//    @ApiImplicitParams({
//            @ApiImplicitParam(name = "key", value = "键", required = true, dataType = "string", paramType = "query"),
//            @ApiImplicitParam(name = "value", value = "值", required = true, dataType = "string", paramType = "query"),
//            @ApiImplicitParam(name = "liveTime", value = "过期时间（秒）", dataType = "int", paramType = "query")
//    })
//    @RequestMapping(value = "/token", method = RequestMethod.POST)
//    public ResponseEntity<ResultObject> setToken(@RequestParam("key") String key,
//                                                 @RequestParam("value") String value,
//                                                 @RequestParam("liveTime") Optional<Integer> liveTime) {
//        tokenService.setString(key, value, liveTime.orElse(null));
//        return new ResponseEntity<>(new ResultObject<>(null), HttpStatus.OK);
//    }

    /**
     * 删除token值
     * @param key 键
     */
//    @ApiOperation("删除token值")
//    @ApiImplicitParams({
//            @ApiImplicitParam(name = "key", value = "键", required = true, dataType = "string", paramType = "query")
//    })
//    @RequestMapping(value = "/token", method = RequestMethod.DELETE)
//    public ResponseEntity<ResultObject> delToken(@RequestParam("key") String key) {
//        tokenService.delString(key);
//        return new ResponseEntity<>(new ResultObject<>(null), HttpStatus.OK);
//    }

    /**
     * 获得token值
     * @param key 键
     */
//    @ApiOperation("获得token值")
//    @ApiImplicitParams({
//            @ApiImplicitParam(name = "key", value = "键", required = true, dataType = "string", paramType = "query")
//    })
//    @RequestMapping(value = "/token", method = RequestMethod.GET)
//    public ResponseEntity<ResultObject> getToken(@RequestParam("key") String key) {
//        String value = tokenService.getString(key);
//        return new ResponseEntity<>(new ResultObject<>(value), HttpStatus.OK);
//    }

    /**
     * 是否存在token键
     * @param key 键
     */
//    @ApiOperation("是否存在token键")
//    @ApiImplicitParams({
//            @ApiImplicitParam(name = "key", value = "键", required = true, dataType = "string", paramType = "query")
//    })
//    @RequestMapping(value = "/token/exists", method = RequestMethod.GET)
//    public ResponseEntity<ResultObject> hasToken(@RequestParam("key") String key) {
//        boolean exists = tokenService.hasKey(key);
//        return new ResponseEntity<>(new ResultObject<>(exists), HttpStatus.OK);
//    }

    /**
     * 添加验证码
     * @param key 键
     * @param value 值
     * @param liveTime 过期时间（秒）
     */
//    @ApiOperation("添加验证码")
//    @ApiImplicitParams({
//            @ApiImplicitParam(name = "key", value = "键", required = true, dataType = "string", paramType = "query"),
//            @ApiImplicitParam(name = "value", value = "值", required = true, dataType = "string", paramType = "query"),
//            @ApiImplicitParam(name = "liveTime", value = "过期时间（秒）", dataType = "int", paramType = "query")
//    })
//    @RequestMapping(value = "/verificationCode", method = RequestMethod.POST)
//    public ResponseEntity<ResultObject> setVerificationCode(@RequestParam("key") String key,
//                                                            @RequestParam("value") String value,
//                                                            @RequestParam("liveTime") Optional<Integer> liveTime) {
//        tokenService.setString(key, value, liveTime.orElse(null));
//        return new ResponseEntity<>(new ResultObject<>(null), HttpStatus.OK);
//    }

    /**
     * 删除验证码
     * @param key 键
     */
//    @ApiOperation("删除验证码")
//    @ApiImplicitParams({
//            @ApiImplicitParam(name = "key", value = "键", required = true, dataType = "string", paramType = "query")
//    })
//    @RequestMapping(value = "/verificationCode", method = RequestMethod.DELETE)
//    public ResponseEntity<ResultObject> delVerificationCode(@RequestParam("key") String key) {
//        tokenService.delString(key);
//        return new ResponseEntity<>(new ResultObject<>(null), HttpStatus.OK);
//    }

    /**
     * 获得验证码
     * @param key 键1
     */
//    @ApiOperation("获得验证码")
//    @ApiImplicitParams({
//            @ApiImplicitParam(name = "key", value = "键", required = true, dataType = "string", paramType = "query")
//    })
//    @RequestMapping(value = "/verificationCode", method = RequestMethod.GET)
//    public ResponseEntity<ResultObject> getVerificationCode(@RequestParam("key") String key) {
//        String value = tokenService.getString(key);
//        return new ResponseEntity<>(new ResultObject<>(value), HttpStatus.OK);
//    }


    /**
     * 根据手机号和密码获得用户（执行登录）
     * @param phone 键
     * @param password 值
     */
    @ApiOperation("根据手机号和密码获得用户（执行登录）")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "phone", value = "手机号", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "password", value = "密码", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "systemId", value = "系统标识", dataType = "string", paramType = "query")
    })
    @RequestMapping(value="/loginByPhone", method = RequestMethod.POST)
    public ResponseEntity<ResultObject> login(@RequestParam("phone") Optional<String> phone,
                                              @RequestParam("password") Optional<String> password,
                                              @RequestParam("systemId") Optional<String> systemId)
            throws ArgumentErrorException, UsernamePasswordException {
        if (!phone.isPresent()) {
            throw new UsernamePasswordException("手机号不能为空");
        } else if (!password.isPresent()) {
            throw new UsernamePasswordException("密码不能为空");
        }else if(!systemId.isPresent()){
            throw new UsernamePasswordException("系统标识不能为空");
        }
        User user = userService.findByPhoneAndPassword(phone.get(), password.get());
        if(!user.isBackUser() && "1".equals(systemId.orElse(null))){
            throw new ArgumentErrorException("当前用户不是后台用户不能登录后台管理平台!");
        }
        if(user.isBackUser() && "2".equals(systemId.orElse(null))){
            throw new ArgumentErrorException("当前用户不是智慧园区平台用户不能登录智慧园区平台!");
        }
        String token = tokenService.getToken(user,systemId.get());
        Map<String, Object> result = new HashMap<>();
        result.put("token", token);
        result.put("user", user);
        //记录最后登录时间，最后登录系统品平台
        user.setLastLoginSystem(systemId.get());
        user.setLastLoginTime(DateTimeUtils.format(DateTimeUtils.PATTERN.DATETIME.value(),new Date()));
        userService.saveLoginRecord(user);
        //判断该用户是否是重置密码后第一次登录
         Boolean firstLoginFlag = userService.resetFirstLogin(user.getId());
         result.put("firstLoginFlag",firstLoginFlag);
         if(MD5Util.encode(userProperties.getRootDefaultPassword(), SALT_V).equals(password)){
             result.put("firstLoginFlag",false);
         };
         //设置对应的项目
        List<ProjectData> projectDatas = findStationByLoginUser(user);
        if(!CollectionUtil.isEmpty(projectDatas)){
            result.put("project",projectDatas);
            projectDatas.stream().forEach(projectData -> {
                if(projectData.getId().equals(user.getLastAccessProject())){
                    user.setLastAccessProjectTitle(projectData.getTitle());
                }
            });
        }
        return new ResponseEntity<>(new ResultObject<>(result), HttpStatus.OK);
    }

    private List<ProjectData> findStationByLoginUser(User user) {
        List<ProjectData> result = new ArrayList<>();
        //判断当前登录的账号是单位账号还是园区账号
        List<Firm> firms = user.getFirms();
        List<Station> stations = user.getStations();
        if (!CollectionUtil.isEmpty(stations)) {
            for (Station station : stations) {
                ProjectData projectData = new ProjectData();
                projectData.setId(station.getId());
                projectData.setTitle(station.getEnterpriseFullName());
                projectData.setType("station");
                projectData.setSn(station.getSn());
                result.add(projectData);
            }
        }
        if (!CollectionUtil.isEmpty(firms)) {
            for (Firm firm : firms) {
                ProjectData projectData = new ProjectData();
                projectData.setId(firm.getId());
                projectData.setTitle(firm.getEnterpriseFullName());
                projectData.setType("firm");
                projectData.setSn(firm.getSn());
                result.add(projectData);
            }
        }
        //对集合针对每个ProjectData的sn首字母进行升序排序
        result.sort(Comparator.comparing(ProjectData::getSn));
//        Comparator comparator = Collator.getInstance(Locale.CHINA);
//        if (!CollectionUtil.isEmpty(result)) {
//            result = (List<ProjectData>) result.stream().sorted(comparator.thenComparing(Comparator.comparing(ProjectData::getSn))).collect(Collectors.toList());
//        }
        return result;
    }

//    public static void main(String[] args) {
//        List<ProjectData> result = new ArrayList<>();
//        ProjectData projectData = new ProjectData();
//        projectData.setId(1L);
//        projectData.setSn("ABCDYQ");
//        projectData.setTitle("123234");
//        projectData.setType("station");
//        result.add(projectData);
//        ProjectData projectData1 = new ProjectData();
//        projectData1.setId(2L);
//        projectData1.setSn("ABDF");
//        projectData1.setTitle("123233454");
//        projectData1.setType("station");
//        result.add(projectData1);
//        ProjectData projectData2 = new ProjectData();
//        projectData2.setId(2L);
//        projectData2.setSn("ABCD");
//        projectData2.setTitle("123233454");
//        projectData2.setType("station");
//        result.add(projectData2);
//        result.sort(Comparator.comparing(ProjectData::getSn));
//        //Comparator comparator = Collator.getInstance(Locale.CHINA);
//        //result = (List<ProjectData>) result.stream().sorted(comparator.thenComparing(Comparator.comparing(ProjectData::getSn))).collect(Collectors.toList());
//        System.out.println(result);
//    }

    /**
     * 根据手机号和获得用户（忘记密码）
     * @param phone 键
     */
    @ApiOperation("根据手机号获得用户（忘记密码）")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "phone", value = "手机号", dataType = "string", paramType = "query")
    })
    @RequestMapping(value="/getUserByPhone", method = RequestMethod.POST)
    public ResponseEntity<ResultObject> getUserByPhone(@RequestParam("phone") Optional<String> phone)
            throws ArgumentErrorException, UsernamePasswordException, ObjectNotFoundException {
        if (!phone.isPresent()) {
            throw new UsernamePasswordException("手机号不能为空");
        }
        User user = userService.getLoginUserByPhone(phone.get());
        return new ResponseEntity<>(new ResultObject<>(user), HttpStatus.OK);
    }

    /**
     * 发送验证码
     * @param phone 手机号
     */
    @ApiOperation("发送验证码")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "phone", value = "手机号", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "type", value = "验证码类型", required = true, dataType = "string", paramType = "query")
    })
    @RequestMapping(value = "/validate", method = RequestMethod.POST)
    public ResponseEntity<ResultObject> sendValidateMsg(@RequestParam("phone") String phone,
                                                        @RequestParam("type") String type)
            throws ArgumentErrorException {
        userService.sendValidateMsg(phone,type);
        return new ResponseEntity<>(new ResultObject<>(null), HttpStatus.OK);
    }

    @ApiOperation("app发送验证码")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "phone", value = "手机号", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "type", value = "验证码类型", required = true, dataType = "string", paramType = "query")
    })
    @RequestMapping(value = "/validateForMob", method = RequestMethod.POST)
    public ResponseEntity<ResultObject> validateForMob(@RequestBody ValidateCode validateCode)
            throws ArgumentErrorException {
        userService.validateForMob(validateCode.getPhone(),validateCode.getType());
        return new ResponseEntity<>(new ResultObject<>(null), HttpStatus.OK);
    }

    @ApiOperation("小程序发送验证码")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "phone", value = "手机号", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "type", value = "验证码类型", required = true, dataType = "string", paramType = "query")
    })
    @RequestMapping(value = "/validateByWeChat", method = RequestMethod.POST)
    public ResponseEntity<ResultObject> validateByWeChat(@RequestParam("phone") String phone,
                                                        @RequestParam("type") String type)
            throws ArgumentErrorException {
        userService.validateByWeChat(phone,type);
        return new ResponseEntity<>(new ResultObject<>(null), HttpStatus.OK);
    }

    /**
     * 校验验证码是否正确
     * @param phone 手机号
     */
    @ApiOperation("忘记密码")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "phone", value = "手机号", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "verificationCode", value = "验证码", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "password", value = "密码", required = true, dataType = "string", paramType = "query")
    })
    @RequestMapping(value = "/changePassword", method = RequestMethod.POST)
    @OperationRecord(menu = "忘记密码", actionType = SystemConsts.ACTION.EDIT, action = "忘记密码")
    public ResponseEntity<ResultObject> changePassword(@RequestParam("phone") String phone,
                                                        @RequestParam("verificationCode") String verificationCode,
                                                        @RequestParam("password") String password)
            throws ArgumentErrorException {
        if(StringUtil.isEmpty(verificationCode)){
            throw new ArgumentErrorException("请填写验证码");
        }
        return new ResponseEntity<>(new ResultObject<>(userService.changePassword(phone,verificationCode,password)), HttpStatus.OK);
    }

    /**
     * 校验验证码是否正确
     * @param phone 手机号
     */
    @ApiOperation("忘记密码")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "phone", value = "手机号", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "verificationCode", value = "验证码", required = true, dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "password", value = "密码", required = true, dataType = "string", paramType = "query")
    })
    @RequestMapping(value = "/changePasswordForMob", method = RequestMethod.POST)
    @OperationRecord(menu = "app忘记密码", actionType = SystemConsts.ACTION.EDIT, action = "忘记密码")
    public ResponseEntity<ResultObject> changePasswordForMob(@RequestParam("phone") String phone,
                                                       @RequestParam("verificationCode") String verificationCode,
                                                       @RequestParam("password") String password)
            throws ArgumentErrorException {
        if(StringUtil.isEmpty(verificationCode)){
            throw new ArgumentErrorException("请填写验证码");
        }
        return new ResponseEntity<>(new ResultObject<>(userService.changePasswordForMob(phone,verificationCode,password)), HttpStatus.OK);
    }

    /**
     * 根据手机号和验证码获得用户（执行登录）
     * @param phone 键
     * @param verificationCode 值
     */
    @ApiOperation("根据手机号和验证码获得用户（执行登录）")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "phone", value = "手机号", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "verificationCode", value = "密码", dataType = "string", paramType = "query"),
            @ApiImplicitParam(name = "systemId", value = "系统标识", dataType = "string", paramType = "query")
    })
    @RequestMapping(value="/loginByVerificationCode", method = RequestMethod.POST)
    public ResponseEntity<ResultObject> loginByVerificationCode(@RequestParam("phone") Optional<String> phone,
                                              @RequestParam("verificationCode") Optional<String> verificationCode,
                                              @RequestParam("systemId") Optional<String> systemId)
            throws ArgumentErrorException, UsernamePasswordException {
        if (!phone.isPresent()) {
            throw new UsernamePasswordException("手机号不能为空");
        } else if (!verificationCode.isPresent()) {
            throw new UsernamePasswordException("验证码不能为空");
        }else if(!systemId.isPresent()){
            throw new UsernamePasswordException("系统标识不能为空");
        }
        User user = userService.findByPhoneAndVerificationCode(phone.get(), verificationCode.get());
        if(!user.isBackUser() && "1".equals(systemId.orElse(null))){
            throw new ArgumentErrorException("当前用户不是后台用户不能登录后台管理平台!");
        }
        if(user.isBackUser() && "2".equals(systemId.orElse(null))){
            throw new ArgumentErrorException("当前用户不是智慧园区平台用户不能登录智慧园区平台!");
        }
        String token = tokenService.getToken(user,systemId.get());
        Map<String, Object> result = new HashMap<>();
        result.put("token", token);
        result.put("user", user);
        //记录最后登录时间，最后登录系统品平台
        user.setLastLoginSystem(systemId.get());
        user.setLastLoginTime(DateTimeUtils.format(DateTimeUtils.PATTERN.DATETIME.value(),new Date()));
        userService.saveLoginRecord(user);
        //设置对应的项目
        List<ProjectData> projectDatas = findStationByLoginUser(user);
        if(!CollectionUtil.isEmpty(projectDatas)){
            result.put("project",projectDatas);
        }
        return new ResponseEntity<>(new ResultObject<>(result), HttpStatus.OK);
    }

}
